﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using modele.interfaces;
using modele.impl;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Reflection;
using Wrapper;

namespace UI
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    /**
     * \file MainWindow.xaml.cs
     * \brief Fenêtre principale de notre application
     * \author Alexandre Carteron et Charles Robin
     * \version 1.0
     * \date 13/12/2012
     * 
     * Fenêtre principale de notre application
     */
    public partial class MainWindow : Window
    {
        public static MainWindow INSTANCE; /*!<Instance unique de la fenêtre principale*/
        public Jeu jeu { get; private set; } /*!<Permet d'accéder directement au modèle*/
        public GestionTour gestionTour { get; set; } /*!<Permet d'accéder au gestionnaire de tour*/
        public TextBlock[,] textes { get; set; } /*!<Permet d'afficher le nombre d'unité présentes sur une case*/

        /**
         * \fn public MainWindow(int tailleCarte)
         * \brief Constructeur de la classe MainWindow
         * 
         * Constructeur de la première MainWindow 
         * 
         * \param[in] taille entier représentant la taille du coté de la carte
         *
         */
        public MainWindow(int tailleCarte)
        {
            MainWindow.INSTANCE = this;

            textes = new TextBlock[tailleCarte, tailleCarte];

            InitializeComponent();

            jeu = JeuImpl.INSTANCE;
            jeu.creerJeu(tailleCarte);

            FabriqueCarteVue.creerCarte(uiCarte, tailleCarte, JeuImpl.INSTANCE.definitionCarte);

            gestionTour = new GestionTour(tailleCarte);
            gestionTour.
            mettreAJourCarte();
            this.initHandler();
        }

        /**
         * \fn public MainWindow(int tailleCarte, Jeu jeu, GestionTour gestionTour)
         * \brief Constructeur de la classe MainWindow
         * 
         * Constructeur de la MainWindow lors d'un chargement
         * 
         * \param[in] taille entier représentant la taille du coté de la carte
         * \param[in] jeu Jeu permettant d'accéder au nouveau modèle
         * \param[in] gestionTour GestionTour permettant d'accéder au nouveau gestionnaire de tour
         *
         */
        public MainWindow(Jeu jeu, GestionTour gestionTour)
        {
            int tailleCarte = jeu.carte.taille;
            MainWindow.INSTANCE = this;
            brushFactory.reInit();
            TabManager.reInit();

            textes = new TextBlock[tailleCarte, tailleCarte];

            InitializeComponent();

            this.jeu = jeu;
            Console.WriteLine(tailleCarte);

            FabriqueCarteVue.creerCarte(uiCarte, tailleCarte, JeuImpl.INSTANCE.definitionCarte);

            this.gestionTour = gestionTour;
            gestionTour.load();

            this.initHandler();

        }

        bool mouvement = false; /*!<Indique si on est en train de déplacer ou non des unités*/
        int lastX, lastY; /*!<Position du curseur */
        /**
         * \fn public void initHandler()
         * \brief Méthode d'initialisation des handler de la fenêtre principale
         * 
         * Méthode d'initialisation des handler de la fenêtre principale
         * 
         */
        public void initHandler()
        {
            this.KeyDown += new KeyEventHandler((object sender, KeyEventArgs e) =>
            {
                if (e.Key == Key.Space)
                    gestionTour.finTour();
                if (menuGauche.Items.Count > 0)
                {
                    if (e.Key == Key.RightShift)
                        menuGauche.SelectedIndex = (menuGauche.SelectedIndex + 1) % menuGauche.Items.Count;
                    if (e.Key == Key.RightCtrl)
                        menuGauche.SelectedIndex = (menuGauche.SelectedIndex - 1 + menuGauche.Items.Count) % menuGauche.Items.Count;
                }

                int x, y;
                x = jeu.joueurs[jeu.joueurCourant].curseurX;
                y = jeu.joueurs[jeu.joueurCourant].curseurY;

                if (e.Key == Key.Up)
                {
                        if (y > 0)
                        if (mouvement)
                            FabriqueCarteVue.clicDroit(x, y - 1);
                        else
                            FabriqueCarteVue.clicGauche(x, y - 1);
                        lastX = x;
                        lastY = y-1;
                }
                if (e.Key == Key.Down)
                {
                    if (y < jeu.carte.taille - 1)
                        if (mouvement)
                            FabriqueCarteVue.clicDroit(x, y + 1);
                        else
                            FabriqueCarteVue.clicGauche(x, y + 1);
                    lastX = x;
                    lastY = y+1;
                }
                if (e.Key == Key.Right)
                {
                    if (x < jeu.carte.taille - 1)
                        if (mouvement)
                            FabriqueCarteVue.clicDroit(x + 1, y);
                        else
                            FabriqueCarteVue.clicGauche(x + 1, y);
                    lastX = x+1;
                    lastY = y;
                }
                if (e.Key == Key.Left)
                {
                    if (x > 0)
                        if (mouvement)
                            FabriqueCarteVue.clicDroit(x - 1, y);
                        else
                            FabriqueCarteVue.clicGauche(x - 1, y);
                    lastX = x-1;
                    lastY = y;
                }
                if (e.Key == Key.Enter)
                {
                    if (lastX == x && lastY == y && !mouvement)
                    {
                        FabriqueCarteVue.clicGauche(x, y);
                        mouvement = true;
                        this.selectionRectangle.Opacity = 0.5;
                    }
                    else
                    {
                        FabriqueCarteVue.clicGauche(x, y);
                        mouvement = false;
                        this.selectionRectangle.Opacity = 1;
                    }
                    lastX = x;
                    lastY = y;
                }
                if (FabriqueCarteVue.montrer)
                    MainWindow.INSTANCE.montrerProp(x, y);
                else
                    MainWindow.INSTANCE.cacherProp();
            });
        }


        /**
         * \fn public void montrerProp(int x, int y)
         * \brief Affiche les suggestions d'emplacement de ville
         * 
         * Affiche les suggestions d'emplacement de ville
         * 
         * \param[in] x entier représentant l'abscisse de l'enseignant 
         * \param[in] y entier représentant l'ordonnée de l'enseignant 
         * 
         */
        public void montrerProp(int x, int y)
        {
            int prop0 = JeuImpl.INSTANCE.definitionCarte.getEmplacementVille(x, y, 0);
            int prop1 = JeuImpl.INSTANCE.definitionCarte.getEmplacementVille(x, y, 1);
            int prop2 = JeuImpl.INSTANCE.definitionCarte.getEmplacementVille(x, y, 2);

            int x0 = prop0 / JeuImpl.INSTANCE.carte.taille;
            int y0 = prop0 % JeuImpl.INSTANCE.carte.taille;
            int x1 = prop1 / JeuImpl.INSTANCE.carte.taille;
            int y1 = prop1 % JeuImpl.INSTANCE.carte.taille;
            int x2 = prop2 / JeuImpl.INSTANCE.carte.taille;
            int y2 = prop2 % JeuImpl.INSTANCE.carte.taille;

            Grid.SetRow(MainWindow.INSTANCE.proposition0,1);
            Grid.SetColumn(MainWindow.INSTANCE.proposition0, x0);
            //FabriqueCarteVue.lignes[y0].Children.Add(MainWindow.INSTANCE.proposition0);
            MainWindow.INSTANCE.proposition0.Visibility = Visibility.Visible;
            FabriqueCarteVue.addHandlersSuggestions(proposition0, y0,0);
            ((Grid)MainWindow.INSTANCE.proposition0.Parent).Children.Remove(MainWindow.INSTANCE.proposition0);
            FabriqueCarteVue.lignes[y0].Children.Add(MainWindow.INSTANCE.proposition0);


            Grid.SetRow(MainWindow.INSTANCE.proposition1, 1);
            Grid.SetColumn(MainWindow.INSTANCE.proposition1, x1);
            MainWindow.INSTANCE.proposition1.Visibility = Visibility.Visible;
            FabriqueCarteVue.addHandlersSuggestions(proposition1, y1,1);
            ((Grid)MainWindow.INSTANCE.proposition1.Parent).Children.Remove(MainWindow.INSTANCE.proposition1);
            FabriqueCarteVue.lignes[y1].Children.Add(MainWindow.INSTANCE.proposition1);


            Grid.SetRow(MainWindow.INSTANCE.proposition2, 1);
            Grid.SetColumn(MainWindow.INSTANCE.proposition2, x2);
            MainWindow.INSTANCE.proposition2.Visibility = Visibility.Visible;
            FabriqueCarteVue.addHandlersSuggestions(proposition2, y2,2);
            ((Grid)MainWindow.INSTANCE.proposition2.Parent).Children.Remove(MainWindow.INSTANCE.proposition2);
            FabriqueCarteVue.lignes[y2].Children.Add(MainWindow.INSTANCE.proposition2);
        }


        /**
         * \fn public void cacherProp()
         * \brief Cache les suggestions d'emplacement de ville
         * 
         * Cache les suggestions d'emplacement de ville
         * 
         */
        public void cacherProp()
        {
            this.proposition0.Visibility = Visibility.Hidden;
            this.proposition1.Visibility = Visibility.Hidden;
            this.proposition2.Visibility = Visibility.Hidden;
        }

        /**
         * \fn public void finTour(object o, RoutedEventArgs args)
         * \brief Méthode appelée par le bouton fin de tour défini dans le fichier xaml
         * 
         * Méthode appelée par le bouton fin de tour défini dans le fichier xaml
         * 
         */
        private void finTour(object o, RoutedEventArgs args)
        {
            gestionTour.finTour();
        }


        /**
         * \fn public void Sauver_Clic(object sender, RoutedEventArgs e)
         * \brief Méthode appelée par le bouton de sauvegarde
         * 
         * Méthode appelée par le bouton de sauvegarde
         * 
         */
        private void Sauver_Clic(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "save"; // Default file name
            dlg.DefaultExt = ".godwin"; // Default file extension
            dlg.Filter = "Civilisation SaveFiles (.godwin)|*.godwin"; // Filter files by extension
            dlg.InitialDirectory = Assembly.GetExecutingAssembly().Location;
            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string filename = dlg.FileName;
                string filenamesimple = dlg.SafeFileName;


                IFormatter formatter = new BinaryFormatter();
                Stream stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None);
                formatter.Serialize(stream, jeu);
                stream.Close();

                stream = new FileStream(filename+".gestionTour", FileMode.Create, FileAccess.Write, FileShare.None);
                formatter.Serialize(stream, gestionTour);
                stream.Close();
                jeu.saveWrapper(filenamesimple);
            }
        }

        /**
         * \fn public void void Charger_Clic(object sender, RoutedEventArgs e)
         * \brief Méthode appelée par le bouton de chargement
         * 
         * Méthode appelée par le bouton de chargement
         * 
         */
        private void Charger_Clic(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.FileName = "save"; // Default file name
            dlg.DefaultExt = ".godwin"; // Default file extension
            dlg.Filter = "Civilisation SaveFiles (.godwin)|*.godwin"; // Filter files by extension

            // Show save file dialog box
            Nullable<bool> result = dlg.ShowDialog();

            // Process save file dialog box results
            if (result == true)
            {
                // Save document
                string filename = dlg.FileName;
                string filenamesimple = dlg.SafeFileName;

                IFormatter formatter = new BinaryFormatter();
                Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                Jeu jeu = (Jeu)formatter.Deserialize(stream);
                stream.Close();


                stream = new FileStream(filename + ".gestionTour", FileMode.Open, FileAccess.Read, FileShare.Read);
                GestionTour gestionTour = (GestionTour)formatter.Deserialize(stream);
                stream.Close();
                jeu.loadWrapper(filenamesimple);
                FabriqueCarteVue.lignes = new List<Grid>();
                JeuImpl.load((JeuImpl)jeu);
                MainWindow m = new MainWindow(jeu, gestionTour);
                m.Visibility = Visibility.Visible;

                this.Close();
            }
        }

        /**
         * \fn public void void Quitter_Clic(object sender, RoutedEventArgs e)
         * \brief Méthode appelée par le bouton "quitter"
         * 
         * Méthode appelée par le bouton "quitter"
         * 
         */
        private void Quitter_Clic(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = MessageBox.Show(this, "Voulez vous quitter?", "Quitter?", MessageBoxButton.YesNo);
            if (result == MessageBoxResult.Yes)
                this.Close();
        }

        /**
         * \fn public void void Controles_Clic(object sender, RoutedEventArgs e)
         * \brief Méthode appelée par le bouton d'aide pour les contrôles
         * 
         * Méthode appelée par le bouton d'aide pour les contrôles
         * 
         */
        private void Controles_Clic(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = MessageBox.Show(this, "Le clic gauche de la souris sur une cases sert à sélectionner toutes les unités présentes sur la case. Le clic droit permet d'éxécuter les différentes actions pour toutes les unités de la case comme se déplacer et attaquer les autres unités. Il est possible de controler qu'une seule unité en utilisant le clic droit de la souris plus le bouton Ctrl (droit).", "Controles");
        }

        /**
         * \fn public void void Regles_Clic(object sender, RoutedEventArgs e)
         * \brief Méthode appelée par le bouton d'aide pour les règles du jeu
         * 
         * Méthode appelée par le bouton d'aide pour les règles du jeu
         * 
         */
        private void Regles_Clic(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = MessageBox.Show(this, "Civilisation est un jeu de stratégie en tour par tour. Le but du jeu de posséder le plus grand territoire et de gagner les guerres. Pour celà, plusieurs unités sont à dispositions : \n L'étudiant, l'unité militaire \n L'enseignant, le bâtisseur \n Le DirecteurDpt, le Grand Manitou", "Règles");
        }


        /**
         * \fn public void void A_Propos_Clic(object sender, RoutedEventArgs e)
         * \brief Méthode appelée par le bouton d'affichage du menu "à propos"
         * 
         * Méthode appelée par le bouton d'affichage du menu "à propos"
         * 
         */
        private void A_Propos_Clic(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = MessageBox.Show(this, "Civilisation, un projet de 4INFO de l'INSA de RENNES\n réalisé par Alexandre Carteron et Charles Robin","A propos");
        }
    }
}
